<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>使用 PHP 和 DTrace</title>
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-base.css" />
<link media="all" rel="stylesheet" type="text/css" href="styles/03e73060321a0a848018724a6c83de7f-theme-medium.css" />

 </head>
 <body class="docs"><div class="navbar navbar-fixed-top">
  <div class="navbar-inner clearfix">
    <ul class="nav" style="width: 100%">
      <li style="float: left;"><a href="features.dtrace.introduction.html">« PHP 和 DTrace 介绍</a></li>
      <li style="float: right;"><a href="features.dtrace.systemtap.html">使用 SystemTap 监控 PHP DTrace 静态探针 »</a></li>
    </ul>
  </div>
</div>
<div id="breadcrumbs" class="clearfix">
  <ul class="breadcrumbs-container">
    <li><a href="index.html">PHP Manual</a></li>
    <li><a href="features.dtrace.html">DTrace 动态跟踪</a></li>
    <li>使用 PHP 和 DTrace</li>
  </ul>
</div>
<div id="layout">
  <div id="layout-content"><div id="features.dtrace.dtrace" class="sect1">
  <h2 class="title">使用 PHP 和 DTrace</h2>
  <p class="para">
   在支持 DTrace 动态跟踪的平台上，可以配置 PHP 打开 DTrace 静态探针。
  </p>

  <div class="sect2" id="features.dtrace.install">
   <h3 class="title">PHP DTrace 静态探针配置</h3>

   <p class="para">
    请参考操作系统文档获取启用操作系统 DTrace 支持的信息。
    例如，在 Oracle Linux 系统上启动 UEK3 内核，并进行如下操作：
     <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
#&nbsp;modprobe&nbsp;fasttrap<br />#&nbsp;chmod&nbsp;666&nbsp;/dev/dtrace/helper</span>
</code></div>
     </div>

    </div>
   </p>
   <p class="para">
    除了 <code class="literal">chmod</code> 命令，您也可以使用 ACL 包规则来限制特定用户对于设备的访问权限。
   </p>

   <p class="para">
    使用 <code class="literal">--enable-dtrace</code> 配置参数构建 PHP：
    <div class="informalexample">
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
#&nbsp;./configure&nbsp;--enable-dtrace&nbsp;...<br />#&nbsp;make<br />#&nbsp;make&nbsp;install</span>
</code></div>
     </div>

    </div>
   </p>
   <p class="para">
    这样就启用了 PHP 核心的静态探针。对于提供了自有探针的 PHP 扩展需要分别构建。
   </p>
  </div>

  <div class="sect2" id="features.dtrace.static-probes">
  <h3 class="title">PHP 核心的 DTrace 静态探针</h3>
  <table class="doctable table">
   <caption><strong>PHP 中包括以下可用的静态探针</strong></caption>
   
    <thead>
     <tr>
      <th>探针名称</th>
      <th>探针描述</th>
      <th>探针参数</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td><code class="literal">request-startup</code></td>
      <td>请求开始时触发。</td>
      <td>char *<var class="varname">file</var>, char *<var class="varname">request_uri</var>, char *<var class="varname">request_method</var></td>
     </tr>

     <tr>
      <td><code class="literal">request-shutdown</code></td>
      <td>请求关闭时触发。</td>
      <td>char *<var class="varname">file</var>, char *<var class="varname">request_uri</var>, char *<var class="varname">request_method</var></td>
     </tr>

     <tr>
      <td><code class="literal">compile-file-entry</code></td>
      <td>脚本开始编译时触发。</td>
      <td>char *<var class="varname">compile_file</var>, char *<var class="varname">compile_file_translated</var></td>
     </tr>

     <tr>
      <td><code class="literal">compile-file-return</code></td>
      <td>脚本完成编译时触发。</td>
      <td>char *<var class="varname">compile_file</var>, char *<var class="varname">compile_file_translated</var></td>
     </tr>

     <tr>
      <td><code class="literal">execute-entry</code></td>
      <td>操作数数组开始执行时触发。例如：函数调用，文件包含以及生成器恢复时会被触发。</td>
      <td>char *<var class="varname">request_file</var>, int <var class="varname">lineno</var></td>
     </tr>

     <tr>
      <td><code class="literal">execute-return</code></td>
      <td>操作数数组执行完毕之后触发。</td>
      <td>char *<var class="varname">request_file</var>, int <var class="varname">lineno</var></td>
     </tr>

     <tr>
      <td><code class="literal">function-entry</code></td>
      <td>PHP 引擎进入 PHP 函数或者方法调用时触发。</td>
      <td>char *<var class="varname">function_name</var>, char *<var class="varname">request_file</var>, int <var class="varname">lineno</var>, char *<var class="varname">classname</var>, char *<var class="varname">scope</var></td>
     </tr>

     <tr>
      <td><code class="literal">function-return</code></td>
      <td>PHP 引擎从 PHP 函数或者方法调用返回后触发。.</td>
      <td>char *<var class="varname">function_name</var>, char *<var class="varname">request_file</var>, int <var class="varname">lineno</var>, char *<var class="varname">classname</var>, char *<var class="varname">scope</var></td>
     </tr>

     <tr>
      <td><code class="literal">exception-thrown</code></td>
      <td>有异常抛出时触发。</td>
      <td>char *<var class="varname">classname</var></td>
     </tr>

     <tr>
      <td><code class="literal">exception-caught</code></td>
      <td>有异常被捕获时触发。</td>
      <td>char *<var class="varname">classname</var></td>
     </tr>

     <tr>
      <td><code class="literal">error</code></td>
      <td>无论 <a href="errorfunc.configuration.html#ini.error-reporting" class="link">error_reporting</a> 的设定如何，在发生错误时都会触发。</td>
      <td>char *<var class="varname">errormsg</var>, char *<var class="varname">request_file</var>, int <var class="varname">lineno</var></td>
     </tr>

    </tbody>
   
  </table>

  <p class="para">
   PHP 扩展可以拥有额外的静态探针。
  </p>
  </div>

  <div class="sect2" id="features.dtrace.list-probes">
   <h3 class="title">列出 PHP 中可用的静态探针</h3>
   <p class="para">
    要列出 PHP 中可用的静态探针，开启一个 PHP 进程，然后运行：
    <div class="informalexample">
     <div class="example-contents">
<div class="cdata"><pre>
# dtrace -l
</pre></div>
     </div>

    </div>
   </p>

   <p class="para">
    输出信息类似如下所示：
    <div class="informalexample">
     <div class="example-contents">
<div class="cdata"><pre>
   ID   PROVIDER            MODULE                          FUNCTION NAME
   [ . . . ]
    4   php15271               php               dtrace_compile_file compile-file-entry
    5   php15271               php               dtrace_compile_file compile-file-return
    6   php15271               php                        zend_error error
    7   php15271               php  ZEND_CATCH_SPEC_CONST_CV_HANDLER exception-caught
    8   php15271               php     zend_throw_exception_internal exception-thrown
    9   php15271               php                 dtrace_execute_ex execute-entry
   10   php15271               php           dtrace_execute_internal execute-entry
   11   php15271               php                 dtrace_execute_ex execute-return
   12   php15271               php           dtrace_execute_internal execute-return
   13   php15271               php                 dtrace_execute_ex function-entry
   14   php15271               php                 dtrace_execute_ex function-return
   15   php15271               php              php_request_shutdown request-shutdown
   16   php15271               php               php_request_startup request-startup
</pre></div>
     </div>

    </div>
   </p>

   <p class="para">
    Provider 一列由 <code class="literal">php</code> 和当前进程 id 的组成。
   </p>

   <p class="para">
    如果运行的是 Apache web 服务器，那么模块名称可能是 <var class="filename">libphp5.so</var>，
    并且可能会出现多块信息，每个运行中的 Apache 进程对应一个输出块。
   </p>

   <p class="para">
    Function Name 一列表示 Provider 对应的 PHP 内部 C 实现函数名称。
   </p>

   <p class="para">
    如果没有运行任何 PHP 进程，那么就不会显示任何 PHP 探针。
   </p>
  </div>

  <div class="sect2" id="features.dtrace.examples">
   <h3 class="title">PHP DTrace 示例</h3>
   <p class="para">
    下例展示了基本的 DTrace D 脚本。
    <div class="example" id="example-497">
     <p><strong>示例 #1 <var class="filename">all_probes.d</var> for tracing all PHP Static Probes with DTrace</strong></p>
     <div class="example-contents">
<div class="cdata"><pre>
#!/usr/sbin/dtrace -Zs

#pragma D option quiet

php*:::compile-file-entry
{
    printf(&quot;PHP compile-file-entry\n&quot;);
    printf(&quot;  compile_file              %s\n&quot;, copyinstr(arg0));
    printf(&quot;  compile_file_translated   %s\n&quot;, copyinstr(arg1));
}

php*:::compile-file-return
{
    printf(&quot;PHP compile-file-return\n&quot;);
    printf(&quot;  compile_file              %s\n&quot;, copyinstr(arg0));
    printf(&quot;  compile_file_translated   %s\n&quot;, copyinstr(arg1));
}

php*:::error
{
    printf(&quot;PHP error\n&quot;);
    printf(&quot;  errormsg                  %s\n&quot;, copyinstr(arg0));
    printf(&quot;  request_file              %s\n&quot;, copyinstr(arg1));
    printf(&quot;  lineno                    %d\n&quot;, (int)arg2);
}

php*:::exception-caught
{
    printf(&quot;PHP exception-caught\n&quot;);
    printf(&quot;  classname                 %s\n&quot;, copyinstr(arg0));
}

php*:::exception-thrown
{
    printf(&quot;PHP exception-thrown\n&quot;);
    printf(&quot;  classname                 %s\n&quot;, copyinstr(arg0));
}

php*:::execute-entry
{
    printf(&quot;PHP execute-entry\n&quot;);
    printf(&quot;  request_file              %s\n&quot;, copyinstr(arg0));
    printf(&quot;  lineno                    %d\n&quot;, (int)arg1);
}

php*:::execute-return
{
    printf(&quot;PHP execute-return\n&quot;);
    printf(&quot;  request_file              %s\n&quot;, copyinstr(arg0));
    printf(&quot;  lineno                    %d\n&quot;, (int)arg1);
}

php*:::function-entry
{
    printf(&quot;PHP function-entry\n&quot;);
    printf(&quot;  function_name             %s\n&quot;, copyinstr(arg0));
    printf(&quot;  request_file              %s\n&quot;, copyinstr(arg1));
    printf(&quot;  lineno                    %d\n&quot;, (int)arg2);
    printf(&quot;  classname                 %s\n&quot;, copyinstr(arg3));
    printf(&quot;  scope                     %s\n&quot;, copyinstr(arg4));
}

php*:::function-return
{
    printf(&quot;PHP function-return\n&quot;);
    printf(&quot;  function_name             %s\n&quot;, copyinstr(arg0));
    printf(&quot;  request_file              %s\n&quot;, copyinstr(arg1));
    printf(&quot;  lineno                    %d\n&quot;, (int)arg2);
    printf(&quot;  classname                 %s\n&quot;, copyinstr(arg3));
    printf(&quot;  scope                     %s\n&quot;, copyinstr(arg4));
}

php*:::request-shutdown
{
    printf(&quot;PHP request-shutdown\n&quot;);
    printf(&quot;  file                      %s\n&quot;, copyinstr(arg0));
    printf(&quot;  request_uri               %s\n&quot;, copyinstr(arg1));
    printf(&quot;  request_method            %s\n&quot;, copyinstr(arg2));
}

php*:::request-startup
{
    printf(&quot;PHP request-startup\n&quot;);
    printf(&quot;  file                      %s\n&quot;, copyinstr(arg0));
    printf(&quot;  request_uri               %s\n&quot;, copyinstr(arg1));
    printf(&quot;  request_method            %s\n&quot;, copyinstr(arg2));
}
</pre></div>
     </div>

    </div>
   </p>

   <p class="para">
    此脚本在 <var class="filename">dtrace</var> 命令中使用了 <code class="literal">-Z</code> 选项。
    此选项保证即使在没有任何 PHP 进程运行的时候脚本也能够正确执行。
    如果省略了此选项，当没有任何探针可监控的时候，脚本会立即终止执行。
   </p>

   <p class="para">
    在运行此脚本的过程中，它将监控全部 PHP 核心静态探针。
    运行 D 脚本：
    <div class="informalexample">
     <div class="example-contents">
<div class="cdata"><pre>
# ./all_probes.d
</pre></div>
     </div>

    </div>
   </p>

   <p class="para">
    再运行一个 PHP 脚本或者 PHP 应用，用来进行监控的 D 脚本会输出每个探针被触发时所携带的参数。
   </p>

   <p class="para">
    监控完成之后，使用
    <code class="literal">^C</code> 来终止 D 脚本的执行。
   </p>

   <p class="para">
    在多 CPU 的主机上，探针的显示顺序可能不是连续的，这取决于哪颗 CPU 执行探针以及多个 CPU 之间的线程迁移情况。
    可以通过显示探针时间戳来减少混淆，例如：
    <div class="informalexample">
     <div class="example-contents">
<div class="cdata"><pre>
php*:::function-entry
{
      printf(&quot;%lld: PHP function-entry &quot;, walltimestamp);
      [ . . .]
}
</pre></div>
     </div>

    </div>
   </p>
  </div>

  <div class="sect2" id="features.dtrace.references">
   <h3 class="title">参见</h3>
   <ul class="simplelist">
    <li class="member"><a href="oci8.dtrace.html" class="link">OCI8 和 DTrace 动态跟踪</a></li>
   </ul>
  </div>
 </div></div></div></body></html>